package com.example.consumer;

import com.example.common.RandomUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Board2 {
    private static final int n = 3, N = 9;
    private static final char notNumber = '.';
    private final char[][] board;
    private List<Set<Character>> row;
    private List<Set<Character>> column;
    private List<Set<Character>> square;

    public Board2(char[][] board) {
        this.board = board;
        row = new ArrayList<>();
        column = new ArrayList<>();
        square = new ArrayList<>();
        for (int i = 0; i < N; i++) {
            row.add(new HashSet<>());
            column.add(new HashSet<>());
            square.add(new HashSet<>());
        }
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                char c = board[i][j];
                if (c != notNumber) {
                    int s1= i/3, s2 = j/3;
                    row.get(i).add(c);
                    column.get(j).add(c);
                    square.get(n * s1 + s2).add(c);
                }
            }
        }
    }

    public char[][] getBoard() {
        return board;
    }

    @Override
    public String toString() {
        int sum = getNumberCount();
        StringBuilder sb = new StringBuilder();
        sb.append("初始数字").append(sum).append("个");
        sb.append("\n");
        for (int i = 0; i < board.length; i++) {
            sb.append(board[i]).append("\n");
        }
        return sb.toString();
    }

    public int getNumberCount() {
        return row.stream().mapToInt(Set::size).sum();
    }

    public String join() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < board.length; i++) {
            sb.append(board[i]);
        }
        return sb.toString();
    }

    public boolean tryInsert(int x, int y, char c) {
        if (row.get(x).contains(c) || column.get(y).contains(c)) {
            return false;
        }
        int s1 = x / 3, s2 = y / 3;
        if (column.get(n * s1 + s2).contains(c)) {
            return false;
        }
        board[x][y] = c;
        row.get(x).add(c);
        column.get(y).add(c);
        column.get(n * s1 + s2).add(c);
        return true;
    }

    public boolean canInsert(int x, int y, char c) {
        if (row.get(x).contains(c) || column.get(y).contains(c)) {
            return false;
        }
        int s1 = x / 3, s2 = y / 3;
        return !column.get(n * s1 + s2).contains(c);
    }

    public void randomInsert(int insertCount) {
        while (insertCount > 0) {
            int randomInt = RandomUtils.getRandomInt(81);
            int x1 = randomInt / 9;
            int y1 = randomInt % 9;
            if (this.board[x1][y1] == '.') {
                int randomInt1 = RandomUtils.getRandomInt(9);
                char c = (char) ('1' + randomInt1);
                if (tryInsert(x1, y1, c)) {
                    insertCount--;
                }
            }
        }
    }
}
